home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_08 / phillip2 / edge.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-14  |  18.4 KB  |  770 lines

  1.  
  2.  
  3.        /***********************************************
  4.        *
  5.        *       file d:\cips\edge.c
  6.        *
  7.        *       Functions: This file contains
  8.        *          detect_edges
  9.        *          setup_masks
  10.        *          get_edge_options
  11.        *          perform_convolution
  12.        *          quick_edge
  13.        *          fix_edges
  14.        *
  15.        *       Purpose:
  16.        *          These functions implement several
  17.        *          types of basic edge detection.
  18.        *
  19.        *       External Calls:
  20.        *          wtiff.c - round_off_image_size
  21.        *                    create_file_if_needed
  22.        *                    write_array_into_tiff_image
  23.        *          tiff.c - read_tiff_header
  24.        *          rtiff.c - read_tiff_image
  25.        *          numcvrt.c - get_integer
  26.        *
  27.        *
  28.        *       Modifications:
  29.        *          27 January 1991 - created
  30.        *          27 December 1992 - Fixed an error in
  31.        *              how I did the 8 direction edge
  32.        *              detectors.  I was only detecting
  33.        *              edges in the last (the 7)
  34.        *              direction.  I fixed this by
  35.        *              setting the out_image to the sum
  36.        *              only if the sum was greater than
  37.        *              the out_image.  This is in the
  38.        *              function perform_convolution.
  39.        *
  40.        *************************************************/
  41.  
  42. #include "cips.h"
  43.  
  44.  
  45.  
  46.  
  47.  
  48. short quick_mask[3][3] =  {
  49.        {-1,  0, -1},
  50.        { 0,  4,  0},
  51.        {-1,  0, -1} };
  52.  
  53.  
  54.    /***************************
  55.    *
  56.    *   Directions for the masks
  57.    *  3 2 1
  58.    *  4 x 0
  59.    *  5 6 7
  60.    *
  61.    ****************************/
  62.  
  63.    /* masks for kirsch operator */
  64. short kirsch_mask_0[3][3] =  {
  65.        { 5,  5,  5},
  66.        {-3,  0, -3},
  67.        {-3, -3, -3} };
  68.  
  69. short kirsch_mask_1[3][3] =  {
  70.        {-3,  5,  5},
  71.        {-3,  0,  5},
  72.        {-3, -3, -3} };
  73.  
  74. short kirsch_mask_2[3][3] =  {
  75.        {-3, -3,  5},
  76.        {-3,  0,  5},
  77.        {-3, -3,  5} };
  78.  
  79. short kirsch_mask_3[3][3] =  {
  80.        {-3, -3, -3},
  81.        {-3,  0,  5},
  82.        {-3,  5,  5} };
  83.  
  84. short kirsch_mask_4[3][3] =  {
  85.        {-3, -3, -3},
  86.        {-3,  0, -3},
  87.        { 5,  5,  5} };
  88.  
  89. short kirsch_mask_5[3][3] =  {
  90.        {-3, -3, -3},
  91.        { 5,  0, -3},
  92.        { 5,  5, -3} };
  93.  
  94. short kirsch_mask_6[3][3] =  {
  95.        { 5, -3, -3},
  96.        { 5,  0, -3},
  97.        { 5, -3, -3} };
  98.  
  99. short kirsch_mask_7[3][3] =  {
  100.        { 5,  5, -3},
  101.        { 5,  0, -3},
  102.        {-3, -3, -3} };
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.    /* masks for prewitt operator */
  110.  
  111. short prewitt_mask_0[3][3] =  {
  112.        { 1,  1,  1},
  113.        { 1, -2,  1},
  114.        {-1, -1, -1} };
  115.  
  116. short prewitt_mask_1[3][3] =  {
  117.        { 1,  1,  1},
  118.        { 1, -2, -1},
  119.        { 1, -1, -1} };
  120.  
  121. short prewitt_mask_2[3][3] =  {
  122.        { 1,  1, -1},
  123.        { 1, -2, -1},
  124.        { 1,  1, -1} };
  125.  
  126. short prewitt_mask_3[3][3] =  {
  127.        { 1, -1, -1},
  128.        { 1, -2, -1},
  129.        { 1,  1,  1} };
  130.  
  131. short prewitt_mask_4[3][3] =  {
  132.        {-1, -1, -1},
  133.        { 1, -2,  1},
  134.        { 1,  1,  1} };
  135.  
  136. short prewitt_mask_5[3][3] =  {
  137.        {-1, -1,  1},
  138.        {-1, -2,  1},
  139.        { 1,  1,  1} };
  140.  
  141. short prewitt_mask_6[3][3] =  {
  142.        {-1,  1,  1},
  143.        {-1, -2,  1},
  144.        {-1,  1,  1} };
  145.  
  146. short prewitt_mask_7[3][3] =  {
  147.        { 1,  1,  1},
  148.        {-1, -2,  1},
  149.        {-1, -1,  1} };
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.    /* masks for sobel operator */
  157.  
  158. short sobel_mask_0[3][3] =  {
  159.        { 1,  2,  1},
  160.        { 0,  0,  0},
  161.        {-1, -2, -1} };
  162.  
  163. short sobel_mask_1[3][3] =  {
  164.        { 2,  1,  0},
  165.        { 1,  0, -1},
  166.        { 0, -1, -2} };
  167.  
  168. short sobel_mask_2[3][3] =  {
  169.        { 1,  0, -1},
  170.        { 2,  0, -2},
  171.        { 1,  0, -1} };
  172. short sobel_mask_3[3][3] =  {
  173.        { 0, -1, -2},
  174.        { 1,  0, -1},
  175.        { 2,  1,  0} };
  176.  
  177. short sobel_mask_4[3][3] =  {
  178.        {-1, -2, -1},
  179.        { 0,  0,  0},
  180.        { 1,  2,  1} };
  181.  
  182. short sobel_mask_5[3][3] =  {
  183.        {-2, -1,  0},
  184.        {-1,  0,  1},
  185.        { 0,  1,  2} };
  186.  
  187. short sobel_mask_6[3][3] =  {
  188.        {-1,  0,  1},
  189.        {-2,  0,  2},
  190.        {-1,  0,  1} };
  191.  
  192. short sobel_mask_7[3][3] =  {
  193.        { 0,  1,  2},
  194.        {-1,  0,  1},
  195.        {-2, -1,  0} };
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.   /**************************************************
  203.   *
  204.   *   detect_edges(...
  205.   *
  206.   *   This function detects edges in an area of one
  207.   *   image and sends the result to another image
  208.   *   on disk.  It reads the input image from disk,
  209.   *   calls a convolution function, and then writes
  210.   *   the result out to disk.  If needed, it
  211.   *   allocates space on disk for the output image.
  212.   *
  213.   ***************************************************/
  214.  
  215.  
  216.  
  217.  
  218. detect_edges(in_name, out_name, the_image, out_image,
  219.              il, ie, ll, le, detect_type, threshold,
  220.              high)
  221.    char   in_name[], out_name[];
  222.    int    detect_type, high, il, ie,
  223.           ll, le, threshold;
  224.    short  the_image[ROWS][COLS], out_image[ROWS][COLS];
  225.  
  226. {
  227.    int    i, j, k, length, width;
  228.    struct tiff_header_struct image_header;
  229.  
  230.  
  231.    create_file_if_needed(in_name, out_name, out_image);
  232.  
  233.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  234.  
  235.    read_tiff_header(in_name, &image_header);
  236.  
  237.    perform_convolution(the_image, out_image,
  238.                        detect_type, threshold,
  239.                        &image_header, high);
  240.  
  241.    fix_edges(out_image, 1);
  242.  
  243.    write_array_into_tiff_image(out_name, out_image,
  244.                                il, ie, ll, le);
  245. }  /* ends detect_edges */
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.      /**********************************************************
  254.      *
  255.      *   perform_convolution(...
  256.      *
  257.      *   This function performs convolution between the input
  258.      *   image and 8 3x3 masks.  The result is placed in
  259.      *   the out_image.
  260.      *
  261.      ********************************************************/
  262.  
  263. perform_convolution(image, out_image,
  264.                     detect_type, threshold,
  265.                     image_header, high)
  266.    short image[ROWS][COLS],
  267.          out_image[ROWS][COLS];
  268.    int   detect_type, high, threshold;
  269.    struct tiff_header_struct *image_header;
  270. {
  271.  
  272.    int a,
  273.        b,
  274.        i,
  275.        is_present,
  276.        j,
  277.        sum;
  278.  
  279.    short  mask_0[3][3],
  280.           mask_1[3][3],
  281.           mask_2[3][3],
  282.           mask_3[3][3],
  283.           mask_4[3][3],
  284.           mask_5[3][3],
  285.           mask_6[3][3],
  286.           mask_7[3][3],
  287.           max,
  288.           min,
  289.           new_hi,
  290.           new_low;
  291.  
  292.  
  293.    setup_masks(detect_type, mask_0, mask_1,
  294.                mask_2, mask_3, mask_4, mask_5,
  295.                mask_6, mask_7);
  296.  
  297.    new_hi  = 250;
  298.    new_low = 16;
  299.    if(image_header->bits_per_pixel == 4){
  300.        new_hi  = 10;
  301.        new_low = 3;
  302.    }
  303.  
  304.    min = 0;
  305.    max = 255;
  306.    if(image_header->bits_per_pixel == 4)
  307.       max = 16;
  308.  
  309.      /* clear output image array */
  310.    for(i=0; i<ROWS; i++)
  311.       for(j=0; j<COLS; j++)
  312.          out_image[i][j] = 0;
  313.  
  314.    printf("\n ");
  315.  
  316.    for(i=1; i<ROWS-1; i++){
  317.       if( (i%10) == 0) printf("%3d", i);
  318.       for(j=1; j<COLS-1; j++){
  319.  
  320.  
  321.          /* Convolve for all 8 directions */
  322.  
  323.          /* 0 direction */
  324.  
  325.       sum = 0;
  326.       for(a=-1; a<2; a++){
  327.          for(b=-1; b<2; b++){
  328.             sum = sum + image[i+a][j+b] *
  329.                   mask_0[a+1][b+1];
  330.          }
  331.       }
  332.          if(sum > max) sum = max;
  333.          if(sum < 0)   sum = 0;
  334.             /* Correction 12-27-92
  335.                see file header for
  336.                details. */
  337.       if(sum > out_image[i][j])
  338.          out_image[i][j]   = sum;
  339.  
  340.  
  341.          /* 1 direction */
  342.  
  343.       sum = 0;
  344.       for(a=-1; a<2; a++){
  345.          for(b=-1; b<2; b++){
  346.             sum = sum + image[i+a][j+b] * mask_1[a+1][b+1];
  347.          }
  348.       }
  349.          if(sum > max) sum = max;
  350.          if(sum < 0)   sum = 0;
  351.             /* Correction 12-27-92
  352.                see file header for
  353.                details. */
  354.       if(sum > out_image[i][j])
  355.          out_image[i][j]   = sum;
  356.  
  357.  
  358.          /* 2 direction */
  359.  
  360.       sum = 0;
  361.       for(a=-1; a<2; a++){
  362.          for(b=-1; b<2; b++){
  363.             sum = sum + image[i+a][j+b] * mask_2[a+1][b+1];
  364.          }
  365.       }
  366.          if(sum > max) sum = max;
  367.          if(sum < 0)   sum = 0;
  368.             /* Correction 12-27-92
  369.                see file header for
  370.                details. */
  371.       if(sum > out_image[i][j])
  372.          out_image[i][j]   = sum;
  373.  
  374.  
  375.          /* 3 direction */
  376.  
  377.       sum = 0;
  378.       for(a=-1; a<2; a++){
  379.          for(b=-1; b<2; b++){
  380.             sum = sum + image[i+a][j+b] * mask_3[a+1][b+1];
  381.          }
  382.       }
  383.          if(sum > max) sum = max;
  384.          if(sum < 0)   sum = 0;
  385.             /* Correction 12-27-92
  386.                see file header for
  387.                details. */
  388.       if(sum > out_image[i][j])
  389.          out_image[i][j]   = sum;
  390.  
  391.  
  392.          /* 4 direction */
  393.  
  394.       sum = 0;
  395.       for(a=-1; a<2; a++){
  396.          for(b=-1; b<2; b++){
  397.             sum = sum + image[i+a][j+b] * mask_4[a+1][b+1];
  398.          }
  399.       }
  400.          if(sum > max) sum = max;
  401.          if(sum < 0)   sum = 0;
  402.             /* Correction 12-27-92
  403.                see file header for
  404.                details. */
  405.       if(sum > out_image[i][j])
  406.          out_image[i][j]   = sum;
  407.  
  408.  
  409.          /* 5 direction */
  410.  
  411.       sum = 0;
  412.       for(a=-1; a<2; a++){
  413.          for(b=-1; b<2; b++){
  414.             sum = sum + image[i+a][j+b] * mask_5[a+1][b+1];
  415.          }
  416.       }
  417.          if(sum > max) sum = max;
  418.          if(sum < 0)   sum = 0;
  419.             /* Correction 12-27-92
  420.                see file header for
  421.                details. */
  422.       if(sum > out_image[i][j])
  423.          out_image[i][j]   = sum;
  424.  
  425.  
  426.          /* 6 direction */
  427.       sum = 0;
  428.       for(a=-1; a<2; a++){
  429.          for(b=-1; b<2; b++){
  430.             sum = sum + image[i+a][j+b] * mask_6[a+1][b+1];
  431.          }
  432.       }
  433.          if(sum > max) sum = max;
  434.          if(sum < 0)   sum = 0;
  435.             /* Correction 12-27-92
  436.                see file header for
  437.                details. */
  438.       if(sum > out_image[i][j])
  439.          out_image[i][j]   = sum;
  440.  
  441.  
  442.          /* 7 direction */
  443.  
  444.       sum = 0;
  445.       for(a=-1; a<2; a++){
  446.          for(b=-1; b<2; b++){
  447.             sum = sum + image[i+a][j+b] * mask_7[a+1][b+1];
  448.          }
  449.       }
  450.          if(sum > max) sum = max;
  451.          if(sum < 0)   sum = 0;
  452.             /* Correction 12-27-92
  453.                see file header for
  454.                details. */
  455.       if(sum > out_image[i][j])
  456.          out_image[i][j]   = sum;
  457.  
  458.  
  459.       }  /* ends loop over j */
  460.    }  /* ends loop over i */
  461.  
  462.  
  463.      /* if desired, threshold the output image */
  464.    if(threshold == 1){
  465.        for(i=0; i<ROWS; i++){
  466.           for(j=0; j<COLS; j++){
  467.              if(out_image[i][j] > high){
  468.                   out_image[i][j] = new_hi;
  469.              }
  470.              else{
  471.                   out_image[i][j] = new_low;
  472.              }
  473.           }
  474.        }
  475.    }  /* ends if threshold == 1 */
  476.  
  477. }  /* ends perform_convolution */
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.      /*******************************************
  486.      *
  487.      *   quick_edge(...
  488.      *
  489.      *   This function finds edges by using
  490.      *   a single 3x3 mask.
  491.      *
  492.      *******************************************/
  493.  
  494.  
  495. quick_edge(in_name, out_name, the_image, out_image,
  496.              il, ie, ll, le, threshold, high)
  497.    char   in_name[], out_name[];
  498.    int    high, il, ie, ll, le, threshold;
  499.    short  the_image[ROWS][COLS], out_image[ROWS][COLS];
  500.  
  501. {
  502.    int    a, b, i, j, k,
  503.           length, max, new_hi, new_low,
  504.           sum, width;
  505.    struct tiff_header_struct image_header;
  506.  
  507.  
  508.    create_file_if_needed(in_name, out_name, out_image);
  509.  
  510.    read_tiff_header(in_name, &image_header);
  511.    new_hi  = 250;
  512.    new_low = 16;
  513.    if(image_header.bits_per_pixel == 4){
  514.        new_hi  = 10;
  515.        new_low = 3;
  516.    }
  517.  
  518.    max = 255;
  519.    if(image_header.bits_per_pixel == 4)
  520.       max = 16;
  521.  
  522.  
  523.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  524.  
  525.          /* Do convolution over image array */
  526.    printf("\n");
  527.    for(i=1; i<ROWS-1; i++){
  528.       if( (i%10) == 0) printf("%d ", i);
  529.       for(j=1; j<COLS-1; j++){
  530.          sum = 0;
  531.          for(a=-1; a<2; a++){
  532.             for(b=-1; b<2; b++){
  533.                sum = sum +
  534.                      the_image[i+a][j+b] *
  535.                      quick_mask[a+1][b+1];
  536.             }
  537.          }
  538.          if(sum < 0)   sum = 0;
  539.          if(sum > max) sum = max;
  540.          out_image[i][j]   = sum;
  541.  
  542.       }  /* ends loop over j */
  543.    }  /* ends loop over i */
  544.  
  545.      /* if desired, threshold the output image */
  546.    if(threshold == 1){
  547.        for(i=0; i<ROWS; i++){
  548.           for(j=0; j<COLS; j++){
  549.              if(out_image[i][j] > high){
  550.                   out_image[i][j] = new_hi;
  551.              }
  552.              else{
  553.                   out_image[i][j] = new_low;
  554.              }
  555.           }
  556.        }
  557.    }  /* ends if threshold == 1 */
  558.  
  559.    fix_edges(out_image, 1);
  560.  
  561.    write_array_into_tiff_image(out_name, out_image,
  562.                                il, ie, ll, le);
  563.  
  564. }  /* ends quick_edge */
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.    /***********************************************
  574.     *
  575.     *    setup_masks(...
  576.     *
  577.     *    This function copies the mask values defined
  578.     *    at the top of this file into the mask
  579.     *    arrays mask_0 through mask_7.
  580.     *
  581.     ***********************************************/
  582.  
  583.  
  584.  
  585. setup_masks(detect_type, mask_0, mask_1, mask_2, mask_3,
  586.             mask_4, mask_5, mask_6, mask_7)
  587.    int    detect_type;
  588.    short  mask_0[3][3],
  589.           mask_1[3][3],
  590.           mask_2[3][3],
  591.           mask_3[3][3],
  592.           mask_4[3][3],
  593.           mask_5[3][3],
  594.           mask_6[3][3],
  595.           mask_7[3][3];
  596. {
  597.    int i, j;
  598.  
  599.    if(detect_type == KIRSCH){
  600.       for(i=0; i<3; i++){
  601.         for(j=0; j<3; j++){
  602.           mask_0[i][j] = kirsch_mask_0[i][j];
  603.           mask_1[i][j] = kirsch_mask_1[i][j];
  604.           mask_2[i][j] = kirsch_mask_2[i][j];
  605.           mask_3[i][j] = kirsch_mask_3[i][j];
  606.           mask_4[i][j] = kirsch_mask_4[i][j];
  607.           mask_5[i][j] = kirsch_mask_5[i][j];
  608.           mask_6[i][j] = kirsch_mask_6[i][j];
  609.           mask_7[i][j] = kirsch_mask_7[i][j];
  610.         }
  611.       }
  612.    }  /* ends if detect_type == KIRSCH */
  613.  
  614.  
  615.    if(detect_type == PREWITT){
  616.       for(i=0; i<3; i++){
  617.         for(j=0; j<3; j++){
  618.           mask_0[i][j] = prewitt_mask_0[i][j];
  619.           mask_1[i][j] = prewitt_mask_1[i][j];
  620.           mask_2[i][j] = prewitt_mask_2[i][j];
  621.           mask_3[i][j] = prewitt_mask_3[i][j];
  622.           mask_4[i][j] = prewitt_mask_4[i][j];
  623.           mask_5[i][j] = prewitt_mask_5[i][j];
  624.           mask_6[i][j] = prewitt_mask_6[i][j];
  625.           mask_7[i][j] = prewitt_mask_7[i][j];
  626.         }
  627.       }
  628.    }  /* ends if detect_type == PREWITT */
  629.  
  630.  
  631.    if(detect_type == SOBEL){
  632.       for(i=0; i<3; i++){
  633.         for(j=0; j<3; j++){
  634.           mask_0[i][j] = sobel_mask_0[i][j];
  635.           mask_1[i][j] = sobel_mask_1[i][j];
  636.           mask_2[i][j] = sobel_mask_2[i][j];
  637.           mask_3[i][j] = sobel_mask_3[i][j];
  638.           mask_4[i][j] = sobel_mask_4[i][j];
  639.           mask_5[i][j] = sobel_mask_5[i][j];
  640.           mask_6[i][j] = sobel_mask_6[i][j];
  641.           mask_7[i][j] = sobel_mask_7[i][j];
  642.         }
  643.       }
  644.    }  /* ends if detect_type == SOBEL */
  645.  
  646.  
  647.  
  648. }  /* ends setup_masks */
  649.  
  650.  
  651.  
  652.    /***********************************************
  653.     *
  654.     *    get_edge_options(...
  655.     *
  656.     *    This function queries the user for the
  657.     *    parameters need to perform edge
  658.     *    detection.
  659.     *
  660.     ***********************************************/
  661.  
  662.  
  663. get_edge_options(detect_type, threshold, high, size)
  664.     int *detect_type, *high, *size, *threshold;
  665. {
  666.     int not_finished, response;
  667.     not_finished = 1;
  668.     while(not_finished){
  669.  
  670.       printf("\nThe Edge Detector options are:\n");
  671.       printf("\n\t1.  Type of edge detector is %d", *detect_type);
  672.       printf("\n\t      (recall 1=Prewitt     2=Kirsch");
  673.       printf("\n\t              3=Sobel       4=quick");
  674.       printf("\n\t              5=homogeneity 6=difference");
  675.       printf("\n\t              7=contrast    8=gaussian");
  676.       printf("\n\t              10=range      11=variance");
  677.       printf("\n\t2.  Threshold output is %d (0=off 1=on)", *threshold);
  678.       printf("\n\t3.  High threshold is %d", *high);
  679.       printf("\n\t4.  Size is %d (gaussian only)", *size);
  680.       printf("\n\nEnter choice (0 = no change) _\b");
  681.  
  682.  
  683.       get_integer(&response);
  684.  
  685.       if(response == 0){
  686.         not_finished = 0;
  687.       }
  688.  
  689.  
  690.       if(response == 1){
  691.         printf("\n\nEnter type of edge detector");
  692.         printf("\n\t      (recall 1=Prewitt     2=Kirsch");
  693.         printf("\n\t              3=Sobel       4=quick");
  694.         printf("\n\t              5=homogeneity 6=difference");
  695.         printf("\n\t              7=contrast    8=gaussian");
  696.         printf("\n\t              10=range      11=variance");
  697.         printf("\n  _\b");
  698.         get_integer(detect_type);
  699.       }
  700.  
  701.       if(response == 2){
  702.         printf("\n\nEnter threshold output (0=off 1=on)");
  703.         printf("\n  _\b");
  704.         get_integer(threshold);
  705.       }
  706.  
  707.       if(response == 3){
  708.         printf("\n\nEnter high threshold");
  709.         printf("\n  _\b");
  710.         get_integer(high);
  711.       }
  712.  
  713.       if(response == 4){
  714.         printf("\n\nEnter size for gaussian (7 or 9)");
  715.         printf("\n  _\b");
  716.         get_integer(size);
  717.       }
  718.     }  /* ends while not_finished */
  719.  
  720. }  /* ends get_edge_options */
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.    /***********************************************
  728.     *
  729.     *    fix_edges(...
  730.     *
  731.     *    This function fixes the edges of an image
  732.     *    array after convolution was performed.
  733.     *    It copies the points near the edge of the
  734.     *    array out to the edge of the array.
  735.     *
  736.     ***********************************************/
  737.  
  738.  
  739.  
  740. fix_edges(im, w)
  741.       int   w;
  742.       short im[ROWS][COLS];
  743. {
  744.    int i, j;
  745.  
  746.  
  747.       /* four corners */
  748.    for(i=w; i>0; i--){
  749.     im[i-1][i-1] = im[i][i];
  750.     im[i-1][COLS-(i-1)] = im[i][COLS-1-(i-1)];
  751.     im[ROWS-(i-1)][i-1] = im[ROWS-1-(i-1)][i];
  752.     im[ROWS-(i-1)][COLS-(i-1)] = im[ROWS-1-(i-1)][COLS-1-(i-1)];
  753.    }  /* ends four corners loop */
  754.  
  755.    for(i=0; i<ROWS; i++){
  756.       for(j=w; j>0; j--){
  757.        im[i][j-1] = im[i][j];
  758.        im[i][COLS-j] = im[i][COLS-j-1];
  759.       }
  760.    }
  761.  
  762.    for(j=0; j<COLS; j++){
  763.       for(i=w; i>0; i--){
  764.        im[i-1][j] = im[i][j];
  765.        im[ROWS-i][j] = im[ROWS-i-1][j];
  766.       }
  767.    }
  768.  
  769. }  /* ends fix_edges */
  770.